package jflowmap.views.heatmap;

import java.awt.Color;
import java.awt.Font;
import java.awt.geom.Point2D;
import java.awt.geom.RoundRectangle2D;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.List;

import jflowmap.model.ontology.Dimension;
import jflowmap.util.piccolo.PNodes;
import edu.umd.cs.piccolo.PCamera;
import edu.umd.cs.piccolo.PNode;
import edu.umd.cs.piccolo.event.PBasicInputEventHandler;
import edu.umd.cs.piccolo.event.PInputEvent;
import edu.umd.cs.piccolo.nodes.PPath;
import edu.umd.cs.piccolo.nodes.PText;
import edu.umd.cs.piccolo.util.PBounds;

public class HeatMapHeader extends PPath {
	private static final long serialVersionUID = 1L;
	
	public static final double TOP_MARGIN = 25;
	public final static Font HEADER_FONT = new Font("Arial", Font.BOLD, 14);
			
	private class HeaderCell extends PNode {
		private static final long serialVersionUID = 1L;
		private final PText text;
		
		public HeaderCell (Dimension dimension) {
			this.text = new PText(dimension.getName());
			this.text.setFont(HEADER_FONT);
			this.addChild(text);
			text.setY(-text.getHeight()/2 - HeatMapHeader.this.cellWidth/2);
			text.rotate(Math.toRadians(90));
		}
		
		public void updatePosition(double y) {
			this.setOffset(this.getXOffset(), HeatMapHeader.this.getY() + 5);
		}
	}

	private final PCamera camera;
	private final VisualHeatMap heatMap;
	private double cellWidth = 0;
	private List<Dimension> valueDimensions = null;

	public HeatMapHeader(PCamera camera, VisualHeatMap visualHeatMap) {
		this.camera = camera;
		this.heatMap = visualHeatMap;

		this.camera.addInputEventListener(new PBasicInputEventHandler() {
			@Override
			public void mouseDragged(PInputEvent event) {
				updatePosition();
			}
		});
		
		this.camera.addPropertyChangeListener(new PropertyChangeListener() {
			@Override
			public void propertyChange(PropertyChangeEvent evt) {
				if (evt.getPropertyName().equals(PCamera.PROPERTY_BOUNDS)) {
					updatePosition();
				}
			}
		});

		this.setVisible(false);
		this.setStroke(null);
		this.setPaint(new Color(240, 240, 240, 230));
	}

	public void update() {
		boolean visible = this.valueDimensions != null && this.valueDimensions.size() > 0;
		this.setVisible(visible);
		if (!visible) return;
		
		this.setPathTo(new RoundRectangle2D.Double(0, -this.getHeight(), cellWidth * valueDimensions.size(), this.getHeight(), 10, 10));
		this.updateBoundsFromPath();
		this.updatePosition();
	}


	public void updatePosition() {
		final PBounds vb = camera.getViewBounds();
		final Point2D origin = this.getGlobalBounds().getOrigin();
		
		vb.y += TOP_MARGIN * camera.getScale();
		
		if (origin.getY() < vb.y) {
			//PNodes.setPosition(this, origin.getX(), vb.y, false);
			this.setBounds(origin.getX(), vb.y, this.getWidth(), this.getHeight());
			
		} else {
			//PNodes.setPosition(this, origin.getX(), -this.getHeight() < vb.y ? vb.y : -this.getHeight(), false);
			this.setBounds(origin.getX(), -this.getHeight() < vb.y ? vb.y : -this.getHeight(), 
					this.getWidth(), this.getHeight());
		}

		for (HeaderCell cell: PNodes.childrenOfType(this, HeaderCell.class)) {
			cell.updatePosition(vb.y);
		}
		
		this.moveToFront();
	}

	public void setCellWidth(double maxCellWidth) {
		this.cellWidth = maxCellWidth;
	}

	public void setValueDimensions(List<Dimension> visibleValueDimensions) {
		this.removeAllChildren();
				
		int counter = 0;
		double maxHeight = 0;
		for (Dimension dim: visibleValueDimensions) {
			HeaderCell dimNode = new HeaderCell(dim);

			PNodes.moveTo(dimNode, this.getX() + cellWidth * counter++ + 2,
					this.getY() + this.getHeight()/2 - dimNode.getHeight()/2);
			this.addChild(dimNode);
			
			if (dimNode.getFullBoundsReference().getHeight() + 10> maxHeight) {
				maxHeight = dimNode.getFullBoundsReference().getHeight() + 10;
			}
		}
		this.setHeight(maxHeight);
		this.valueDimensions = visibleValueDimensions;
		
		this.updatePosition();
	}

}
